#include "bound.hh"

bound::bound ()
{
  v1_ = 0;
  v2_ = 0;
  type_ = FREE;
}

bound::bound (type t, double value)
  : type_ (t),
    v1_ (value)
{
  if (type_ != LOWER && type_ != UPPER && type_ != FIXED)
    throw bad_args (t, 1);
  if (type_ == FIXED)
    v2_ = v1_;
  else
    v2_ = 0;
}

bound::bound (double lvalue, double rvalue)
{
  v1_ = lvalue;
  v2_ = rvalue;
  type_ = DOUBLE;
}

int
bound::get_type ()
{
  switch (type_)
    {
    case FREE:
      return GLP_FR;
    case LOWER:
      return GLP_LO;
    case UPPER:
      return GLP_UP;
    case DOUBLE:
      return GLP_DB;
    case FIXED:
      return GLP_FX;
    }
  return GLP_FX;
}

double
bound::get_lvalue ()
{
  if (v1_ < v2_)
    return v1_;
  return v2_;
}

double
bound::get_rvalue ()
{
  if (v1_ < v2_)
    return v2_;
  return v1_;
}


void
bound::print (std::ostream& stream) const
{
  if (type_ == DOUBLE)
    stream << v1_ << " <= ";
}


bad_args::bad_args (bound::type t, unsigned nb)
  : type_ (t),
    nb_ (nb)
{
}

const char*
bad_args::what() const throw ()
{
  std::ostringstream oss;
  switch (type_)
    {
    case bound::FREE:
      {
	oss << "FREE is expecting 0 argument";
	break;
      }
    case bound::LOWER :
      {
	oss << "LOWER is expecting 1 argument";
	break;
      }
    case bound::UPPER :
      {
	oss << "UPPER is expecting 1 argument";
	break;
      }
    case bound::DOUBLE :
      {
	oss << "DOUBLE is expecting 2 arguments";
	break;
      }
    case bound::FIXED :
      oss << "FIXED is expecting 1 argument";
    }
  oss << " instead of " << nb_ <<" argument";
  return oss.str().c_str();
}


std::ostream& operator << (std::ostream& stream, const bound& w)
{
  switch (w.type_)
    {
    case bound::FREE:
      {
	stream << "free";
	break;
      }
    case bound::LOWER :
      {
	stream << "<= " << w.v1_;
	break;
      }
    case bound::UPPER :
      {
	stream << ">= " << w.v1_;
	break;
      }
    case bound::DOUBLE :
      {
	stream << "<= " << w.v2_;
	break;
      }
    case bound::FIXED :
      stream << "= " << w.v1_;
    }
  return stream;
}
